#pragma once
#include<d3d12.h>
#include<wrl/client.h>
#include <dxgi1_4.h>

#ifdef _DEBUG
#define DX12_ENABLE_DEBUG_LAYER
#endif

#ifdef DX12_ENABLE_DEBUG_LAYER
#include <dxgidebug.h>
#pragma comment(lib, "dxguid.lib")
#endif

using Microsoft::WRL::ComPtr;


namespace Bonnie {
    class CommandList;
    class Framework;

    class Device
    {
        Device() = default;
        static constexpr size_t NUM_BACK_BUFFERS = 3;

        UINT64 mNewestFenceValue = 0;
    private:
        friend class CommandList;
        friend class Framework;

        HANDLE mFenceEvent;
        ComPtr<ID3D12Fence> mFence;
        ComPtr<ID3D12Device> mDevice;
        ComPtr<IDXGISwapChain3> mSwapChain;
        ComPtr<ID3D12CommandQueue> mCmdQueue;
        ComPtr<ID3D12DescriptorHeap> mRtvDescHeap;

        bool isInit = false;
        
        void waitGPUAchieve(UINT64 needAchievedValue);
        bool hasInit()const { return isInit; }
    public:
        static Device* get() {
            static Device ins;
            return &ins;
        }

        void flushCommandQueue();

        bool initDevice(HWND hWnd);

        void onResize(WPARAM wParam, LPARAM lParam);

        /**
        * asynchronous submission
        */ 
        void present(UINT64 finishedFenceValue);

    };
}
